/** uupaa-msgpump.js
 *
 * uupaa-msgpump.js is message pump support javascript library
 *  - uupaa.js spin-off project
 *
 * @author Takao Obara <uupaa.js@gmail.com>
 * @license uupaa-msgpump.js is licensed under the terms and conditions of the MIT licence.
 * @version 0.1
 * @date 2008-12-18
 * @see <a href="http://code.google.com/p/uupaa-js/">uupaa.js Home(Google Code)</a>
 * @see <a href="http://code.google.com/p/uupaa-js-spinoff/">uupaa.js SpinOff Project Home(Google Code)</a>
 */
if (!uuClass.MsgPump) {

/** Message Pump
 *
 * @class
 */
uuClass.MsgPump = function() {
  this._addr = { /* uuid: obj, ... */ };
  this._msg = [ /* num: [ uuid, msg, param1, param2], ... */ ];
  this._run = 0;
};
uuClass.MsgPump.prototype = {
  // uuClass.MsgPump.regist - register the destination of the message
  regist: function(obj /*, ... Object has uuid property */) {
    var a = arguments, v, i = 0, iz = a.length;
    for (; i < iz; ++i) {
      v = a[i];
      if (!v.uuid) { throw TypeError(); }
      this._addr[v.uuid] = v;
    }
    return this;
  },
  // uuClass.MsgPump.unregist
  unregist: function(obj /* , ... */) {
    var a = arguments, v, i = 0, iz = a.length;
    for (; i < iz; ++i) {
      v = a[i];
      if (!v.uuid) { throw TypeError(); }
      delete this._addr[obj.uuid];
    }
    return this;
  },
  // uuClass.MsgPump.send - send a message synchronously
  send: function(to, msg, p1 /* = undefined */, p2 /* = undefined */) {
    var rv = [], v, i, iz, ary;
    if (!to) { // broadcast
      for (i in this._addr) {
        rv.push(this._addr[i].msgbox(msg, p1, p2));
      }
    } else { // unicast, multicast
      ary = (to instanceof Array) ? to : [to];
      for (i = 0, iz = ary.length; i < iz; ++i) {
        v = ary[i];
        rv.push(this._addr[typeof v === "object" ? v.uuid : v].msgbox(msg, p1, p2));
      }
      // if it is an unicast, not the array but the return value is returned.
      if (rv.length === 1) {
        rv = rv[0];
      }
    }
    return rv;
  },
  // uuClass.MsgPump.post - send a message asynchronously
  post: function(to, msg, p1 /* = undefined */, p2 /* = undefined */) {
    var v, i, iz, ary;
    if (!to) { // broadcast
      for (i in this._addr) {
        this._msg.push([i, msg, p1, p2]);
      }
    } else { // unicast, multicast
      ary = (to instanceof Array) ? to : [to];
      for (i = 0, iz = ary.length; i < iz; ++i) {
        v = ary[i];
        this._msg.push([typeof v === "object" ? v.uuid : v, msg, p1, p2]);
      }
    }
    this._runner();
    return this;
  },
  _runner: function() {
    var me = this;
    !this._run && (function() {
      if (!me._msg.length) {
        me._run = 0;
        return;
      }
      var v = me._msg.shift();
      if (v[0] in me._addr) {
        me._addr[v[0]].msgbox(v[1], v[2], v[3]); // (msg, param1, param2)
      }
      me._run = 1;
      setTimeout(arguments.callee, 0);
    })();
  }
};

// --- global instance ---
uu.msg = new uuClass.MsgPump();

} // if (!uuClass.MsgPump)

